package com.sh.data.engine.application.service.dataquality;

import com.alibaba.fastjson.JSONArray;
import com.google.common.collect.Lists;
import com.sh.data.engine.application.model.dto.dataquality.DataQualityTableInfoResponse;
import com.sh.data.engine.application.model.dto.normalization.research.ThemeResponse;
import com.sh.data.engine.application.model.mapper.normalization.ThemeResponseMapper;
import com.sh.data.engine.application.model.request.dataquality.DataQualityAddParExpressionRequest;
import com.sh.data.engine.application.model.request.dataquality.DataQualityRuleRequest;
import com.sh.data.engine.application.model.request.dataquality.SaveDataQualityScheduleRequest;
import com.sh.data.engine.common.exception.BusinessException;
import com.sh.data.engine.common.util.ServletUtils;
import com.sh.data.engine.domain.base.model.PageResult;
import com.sh.data.engine.domain.base.model.UserContext;
import com.sh.data.engine.domain.dataquality.model.domain.*;
import com.sh.data.engine.domain.dataquality.model.param.DataQualityAddParExpressionParam;
import com.sh.data.engine.domain.dataquality.model.param.DataQualityRuleParam;
import com.sh.data.engine.domain.dataquality.model.param.SaveDataQualityScheduleParam;
import com.sh.data.engine.domain.dataquality.service.DataQualityManagerService;
import com.sh.data.engine.domain.normalization.research.themedesign.model.domain.ThemeDomain;
import com.sh.data.engine.domain.normalization.research.themedesign.service.ThemeService;
import com.sh.data.engine.domain.util.ConvertUtil;
import com.sh.data.engine.domain.workspace.manager.model.domain.UserDomain;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author: mengzheng.mhc
 * @date: 2024/7/30 10:35
 */
@Slf4j
@Service
public class DataQualityManagerApplicationService {

    @Autowired
    private DataQualityManagerService dataQualityManagerService;

    @Autowired
    private ThemeService themeService;

    @Autowired
    private ThemeResponseMapper themeResponseMapper;

    public PageResult<DataQualityTableInfoResponse> getTables(
        String tableName, String order, Long themeId, Integer pageNum, Integer pageSize) {
        Long projectId = ServletUtils.getProjectId();

        List<Long> themeIdList;
        if (null != themeId) {
            // 获取某个主题下的子主题
            themeIdList = themeService.getAllChildIdByPid(themeId, projectId);
            // 加入自己的id
            themeIdList.add(themeId);
        } else {
            themeIdList = null;
        }

        PageResult<DataQualityTableInfoDomain> tables =
            dataQualityManagerService.getTables(
                projectId, themeIdList, pageNum, pageSize, tableName, order);

        return ConvertUtil.convertPageInfo(tables, DataQualityTableInfoResponse.class);
    }

    public List<ThemeResponse> getModelDirList() {
        Long projectId = ServletUtils.getProjectId();
        List<ThemeDomain> themesByProjectId = themeService.getThemesByProjectId(projectId);
        return themeResponseMapper.map(themesByProjectId);
    }

    public boolean addParExpression(DataQualityAddParExpressionRequest request) {
        String userId = UserContext.getUserId();
        Long projectId = ServletUtils.getProjectId();
        DataQualityAddParExpressionParam dataQualityAddParExpressionParam =
            ConvertUtil.copyProperties(request, DataQualityAddParExpressionParam.class);

        return dataQualityManagerService.addParExpression(
            dataQualityAddParExpressionParam, projectId, userId);
    }

    public List<DataQualityTablePartitionDomain> getParExpressions(
        Long tblId, String tableName, Integer hasPartition, String parExpression) {
        String userId = UserContext.getUserId();
        Long projectId = ServletUtils.getProjectId();
        return dataQualityManagerService.getParExpressions(
            tblId, tableName, hasPartition, parExpression, projectId, userId);
    }

    public boolean deleteParExpression(Long id) {
        return dataQualityManagerService.deleteParExpression(id);
    }

    public boolean saveRule(DataQualityRuleRequest request) {
        Long projectId = ServletUtils.getProjectId();
        UserDomain userInfo = UserContext.getUserInfo();

        if (request.getRuleDiy() == 0) {
            //      if (request.getRuleFrom() == null) {
            //        throw new BusinessException("规则来源不能为空");
            //      }
            String ruleCompareType = request.getRuleCompareType();
            if (StringUtils.isNotBlank(ruleCompareType) && request.getTemplateId() != 13) {
                // 如果存在比较方式且模版不是枚举值约束
                int ruleCompareTypeSize = ruleCompareType.split(",").length;
                if (ruleCompareTypeSize > 2) {
                    throw new BusinessException("最多选择两个比较方式");
                }
                if (StringUtils.isNotBlank(request.getRuleCondition())) {
                    List<RuleCondition> ruleConditions =
                        JSONArray.parseArray(request.getRuleCondition(), RuleCondition.class);
                    String value = ruleConditions.get(0).getValue();
                    int valueSize = Arrays.asList(value.split(",")).size();
                    if (ruleCompareTypeSize != valueSize) {
                        throw new BusinessException("比较方式个数与期望值个数不匹配");
                    }
                }
            }

            if (request.getRuleType() == null) {
                throw new BusinessException("规则类型不能为空");
            }
            if (request.getTemplateId() == null) {
                throw new BusinessException("规则模版不能为空");
            }
        }
        DataQualityRuleParam dataQualityRuleParam =
            ConvertUtil.copyProperties(request, DataQualityRuleParam.class);

        dataQualityRuleParam.setProjectId(projectId);

        return dataQualityManagerService.saveRule(dataQualityRuleParam, projectId, userInfo);
    }

    public boolean deleteRule(Long id) {
        return dataQualityManagerService.deleteRule(id);
    }

    public PageResult<DataQualityRuleDomain> getRules(Long tblId, Integer ruleDiy, Long parExpressionId, Integer pageNum, Integer pageSize) {
        if (parExpressionId == null) {
            return dataQualityManagerService.rules(tblId, ruleDiy, null, pageNum, pageSize);
        } else {
            return dataQualityManagerService.rules(tblId, ruleDiy, parExpressionId, pageNum, pageSize);
        }
    }

    public DataQualityRuleDetailDomain getRule(Object id) {
        if (id == null || "null".equals(id)) {
            return null;
        }
        return dataQualityManagerService.getRule(Long.valueOf(id.toString()));
    }

    public List<DataQualityRuleTemplateDomain> getRuleTemplates(Integer templateTableType) {
        return dataQualityManagerService.getRuleTemplates(templateTableType);
    }

    public List<DataQualityTableFieldDomain> getTableFields(Long tblId) {
        Long projectId = ServletUtils.getProjectId();
        return dataQualityManagerService.getTableFields(tblId, projectId);
    }

    public DataQualityScheduleDomain getOfflineTaskSchedule(Long tblId) {
        Long projectId = ServletUtils.getProjectId();
        return dataQualityManagerService.getDataQualitySchedule(tblId, projectId);
    }

    public boolean saveOfflineTaskSchedule(SaveDataQualityScheduleRequest request) {
        SaveDataQualityScheduleParam saveDataQualityScheduleParam =
            ConvertUtil.copyProperties(request, SaveDataQualityScheduleParam.class);
        return dataQualityManagerService.saveDataQualitySchedule(
            saveDataQualityScheduleParam, ServletUtils.getProjectId());
    }

    public boolean tryRun(Long tblId, Long partitionId, String rids) {
        List<String> ruleIds = Lists.newArrayList();
        if (StringUtils.isNotBlank(rids)) {
            String[] arr = rids.split(",");
            ruleIds.addAll(Arrays.asList(arr));
        }

        List<Long> ruleIdsLong = ruleIds.stream().map(Long::parseLong).collect(Collectors.toList());

        return dataQualityManagerService.tryRun(
            tblId, partitionId, ruleIdsLong, ServletUtils.getProjectId());
    }
}
